<template>
	<view v-if="show" :style="{ width: systemInfo.width + 'px', height: systemInfo.height + 'px', backgroundColor: bgcolor, position: 'absolute', left: 0, top: 0, zIndex: 9998 }">
		<view
			v-for="(item, rect_idx) in skeletonRectLists"
			:key="rect_idx + 'rect'"
			:class="[loading == 'chiaroscuro' ? 'chiaroscuro' : '']"
			:style="{
				width: item.width + 'px',
				height: item.height + 'px',
				backgroundColor: 'rgb(194, 207, 214,.3)',
				position: 'absolute',
				left: item.left + 'px',
				top: item.top + 'px'
			}"
		></view>
		<view
			v-for="(item, circle_idx) in skeletonCircleLists"
			:key="circle_idx + 'circle'"
			:class="loading == 'chiaroscuro' ? 'chiaroscuro' : ''"
			:style="{
				width: item.width + 'px',
				height: item.height + 'px',
				backgroundColor: 'rgb(194, 207, 214,.3)',
				borderRadius: item.width + 'px',
				position: 'absolute',
				left: item.left + 'px',
				top: item.top + 'px'
			}"
		></view>
		<view class="spinbox" v-if="loading == 'spin'">
			<view class="spin"></view>
		</view>
	</view>
</template>

<script>
export default {
	name: 'skeleton',
	props: {
		bgcolor: {
			type: String,
			value: '#FFF'
		},
		selector: {
			type: String,
			value: 'skeleton'
		},
		loading: {
			type: String,
			value: 'spin'
		},
		show: {
			type: Boolean,
			value: false
		},
		isNodes: {
			type: Number,
			value: false
		} //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
	},
	data() {
		return {
			loadingAni: ['spin', 'chiaroscuro'],
			systemInfo: {},
			skeletonRectLists: [],
			skeletonCircleLists: []
		};
	},
	watch: {
		isNodes(val) {
			this.readyAction();
		}
	},
	mounted() {
		this.attachedAction();
	},
	methods: {
		attachedAction: function () {
			//默认的首屏宽高，防止内容闪现
			const systemInfo = uni.getSystemInfoSync();
			this.systemInfo = {
				width: systemInfo.windowWidth,
				height: systemInfo.windowHeight
			};
			this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
		},
		readyAction: function () {
			const that = this;
			//绘制背景
			uni
				.createSelectorQuery()
				.selectAll(`.${this.selector}`)
				.boundingClientRect()
				.exec(function (res) {
					if (res[0].length > 0) that.systemInfo.height = res[0][0].height + res[0][0].top;
				});

			//绘制矩形
			this.rectHandle();

			//绘制圆形
			this.radiusHandle();
		},
		rectHandle: function () {
			const that = this;

			//绘制不带样式的节点
			uni
				.createSelectorQuery()
				.selectAll(`.${this.selector}-rect`)
				.boundingClientRect()
				.exec(function (res) {
					that.skeletonRectLists = res[0];
				});
		},
		radiusHandle() {
			const that = this;

			uni
				.createSelectorQuery()
				.selectAll(`.${this.selector}-radius`)
				.boundingClientRect()
				.exec(function (res) {
					that.skeletonCircleLists = res[0];
				});
		}
	}
};
</script>

<style>
.spinbox {
	position: fixed;
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100%;
	width: 100%;
	z-index: 9999;
}

.spin {
	display: inline-block;
	width: 64rpx;
	height: 64rpx;
}

.spin:after {
	content: ' ';
	display: block;
	width: 46rpx;
	height: 46rpx;
	margin: 1rpx;
	border-radius: 50%;
	border: 5rpx solid #409eff;
	border-color: #409eff transparent #409eff transparent;
	animation: spin 1.2s linear infinite;
}

@keyframes spin {
	0% {
		transform: rotate(0deg);
	}

	100% {
		transform: rotate(360deg);
	}
}

.chiaroscuro {
	width: 100%;
	height: 100%;
	background: rgb(194, 207, 214);
	animation-duration: 2s;
	animation-name: blink;
	animation-iteration-count: infinite;
}

@keyframes blink {
	0% {
		opacity: 0.4;
	}

	50% {
		opacity: 1;
	}

	100% {
		opacity: 0.4;
	}
}

@keyframes flush {
	0% {
		left: -100%;
	}

	50% {
		left: 0;
	}

	100% {
		left: 100%;
	}
}

.shine {
	animation: flush 2s linear infinite;
	position: absolute;
	top: 0;
	bottom: 0;
	width: 100%;
	background: linear-gradient(to left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.85) 50%, rgba(255, 255, 255, 0) 100%);
}
</style>
